package com.shop.cereshop.app.service.wallet.impl;

import com.shop.cereshop.app.dao.wallet.RechargeDAO;
import com.shop.cereshop.app.service.wallet.RechargeService;
import com.shop.cereshop.app.service.wallet.BuyerWalletService;
import com.shop.cereshop.app.param.wallet.RechargeVO;
import com.shop.cereshop.app.param.wallet.RechargeResponseVO;
import com.shop.cereshop.commons.domain.wallet.Recharge;
import com.shop.cereshop.commons.constant.WalletConstant;
import com.shop.cereshop.commons.utils.TimeUtils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.UUID;

/**
 * 充值服务实现类
 * @author wang.yao
 * @date 2025-08-26
 */
@Slf4j
@Service
public class RechargeServiceImpl implements RechargeService {

    @Autowired
    private RechargeDAO rechargeDAO;

    @Autowired
    private BuyerWalletService buyerWalletService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RechargeResponseVO createRechargeOrder(RechargeVO rechargeVO) {
        try {
            // 验证充值金额
            if (rechargeVO.getAmount().compareTo(new BigDecimal(WalletConstant.WalletConfig.MIN_RECHARGE_AMOUNT)) < 0) {
                throw new IllegalArgumentException("充值金额不能少于" + WalletConstant.WalletConfig.MIN_RECHARGE_AMOUNT + "元");
            }
            
            if (rechargeVO.getAmount().compareTo(new BigDecimal(WalletConstant.WalletConfig.MAX_RECHARGE_AMOUNT)) > 0) {
                throw new IllegalArgumentException("充值金额不能超过" + WalletConstant.WalletConfig.MAX_RECHARGE_AMOUNT + "元");
            }

            // 生成充值单号
            String rechargeNo = generateRechargeNo();
            
            // 计算过期时间
            String expireTime;
            try {
                expireTime = TimeUtils.getMinuteAfter(WalletConstant.WalletConfig.RECHARGE_EXPIRE_MINUTES);
            } catch (Exception e) {
                log.error("计算过期时间失败", e);
                throw new RuntimeException("计算过期时间失败", e);
            }
            
            // 创建充值记录
            Recharge recharge = new Recharge();
            recharge.setBuyerUserId(rechargeVO.getBuyerUserId());
            recharge.setRechargeNo(rechargeNo);
            recharge.setAmount(rechargeVO.getAmount());
            recharge.setPaymentMethod(rechargeVO.getPaymentMethod());
            recharge.setPaymentStatus(WalletConstant.PaymentStatus.PENDING);
            recharge.setExpireTime(expireTime);
            recharge.setRemark(rechargeVO.getRemark());
            recharge.setCreateTime(TimeUtils.yyMMddHHmmss());
            recharge.setUpdateTime(TimeUtils.yyMMddHHmmss());
            
            // 保存充值记录
            rechargeDAO.insert(recharge);
            
            // 构建响应
            RechargeResponseVO responseVO = new RechargeResponseVO();
            responseVO.setRechargeId(recharge.getRechargeId());
            responseVO.setRechargeNo(recharge.getRechargeNo());
            responseVO.setAmount(recharge.getAmount());
            responseVO.setPaymentMethod(recharge.getPaymentMethod());
            responseVO.setPaymentStatus(recharge.getPaymentStatus());
            responseVO.setExpireTime(recharge.getExpireTime());
            responseVO.setCreateTime(recharge.getCreateTime());
            
            // TODO: 根据支付方式生成支付参数
            // 这里先返回空，后续根据具体支付方式实现
            responseVO.setPaymentParams("{}");
            responseVO.setPaymentUrl("");
            
            log.info("用户{}创建充值订单成功，单号：{}，金额：{}", 
                    rechargeVO.getBuyerUserId(), rechargeNo, rechargeVO.getAmount());
            
            return responseVO;
        } catch (Exception e) {
            log.error("创建充值订单失败，用户ID：{}，金额：{}", 
                     rechargeVO.getBuyerUserId(), rechargeVO.getAmount(), e);
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean handleRechargeSuccess(String rechargeNo, String thirdPartyOrderNo) {
        try {
            // 查询充值记录
            Recharge recharge = rechargeDAO.selectByRechargeNo(rechargeNo);
            if (recharge == null) {
                log.warn("充值记录不存在，单号：{}", rechargeNo);
                return false;
            }
            
            // 检查充值状态
            if (!WalletConstant.PaymentStatus.PENDING.equals(recharge.getPaymentStatus())) {
                log.warn("充值订单状态不正确，单号：{}，状态：{}", rechargeNo, recharge.getPaymentStatus());
                return false;
            }
            
            // 更新充值状态
            String updateTime = TimeUtils.yyMMddHHmmss();
            int result = rechargeDAO.updatePaymentStatus(rechargeNo, 
                                                        WalletConstant.PaymentStatus.SUCCESS,
                                                        thirdPartyOrderNo,
                                                        updateTime,
                                                        updateTime);
            
            if (result > 0) {
                // 更新钱包余额
                boolean walletUpdated = buyerWalletService.updateBalance(
                    recharge.getBuyerUserId(),
                    recharge.getAmount(),
                    WalletConstant.TransactionType.RECHARGE,
                    rechargeNo,
                    "钱包充值"
                );
                
                if (walletUpdated) {
                    log.info("充值成功处理完成，单号：{}，用户：{}，金额：{}", 
                            rechargeNo, recharge.getBuyerUserId(), recharge.getAmount());
                    return true;
                } else {
                    log.error("更新钱包余额失败，单号：{}", rechargeNo);
                    return false;
                }
            }
            
            return false;
        } catch (Exception e) {
            log.error("处理充值成功失败，单号：{}", rechargeNo, e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean handleRechargeFail(String rechargeNo, String failReason) {
        try {
            // 查询充值记录
            Recharge recharge = rechargeDAO.selectByRechargeNo(rechargeNo);
            if (recharge == null) {
                log.warn("充值记录不存在，单号：{}", rechargeNo);
                return false;
            }
            
            // 更新充值状态
            String updateTime = TimeUtils.yyMMddHHmmss();
            int result = rechargeDAO.updatePaymentStatus(rechargeNo, 
                                                        WalletConstant.PaymentStatus.FAILED,
                                                        null,
                                                        null,
                                                        updateTime);
            
            if (result > 0) {
                log.info("充值失败处理完成，单号：{}，失败原因：{}", rechargeNo, failReason);
                return true;
            }
            
            return false;
        } catch (Exception e) {
            log.error("处理充值失败异常，单号：{}", rechargeNo, e);
            return false;
        }
    }

    @Override
    public List<Recharge> getRechargeList(Long buyerUserId, Integer page, Integer size) {
        try {
            // 计算偏移量
            int offset = (page - 1) * size;
            int limit = size;
            
            // 查询充值记录
            List<Recharge> rechargeList = rechargeDAO.selectByUserId(buyerUserId, limit);
            
            log.info("查询用户{}充值记录，页码：{}，每页大小：{}，结果数量：{}", 
                    buyerUserId, page, size, rechargeList.size());
            
            return rechargeList;
        } catch (Exception e) {
            log.error("查询充值记录失败，用户ID：{}", buyerUserId, e);
            return null;
        }
    }

    @Override
    public Recharge getRechargeDetail(String rechargeNo) {
        try {
            Recharge recharge = rechargeDAO.selectByRechargeNo(rechargeNo);
            
            if (recharge != null) {
                log.info("查询充值详情成功，单号：{}", rechargeNo);
            } else {
                log.warn("充值记录不存在，单号：{}", rechargeNo);
            }
            
            return recharge;
        } catch (Exception e) {
            log.error("查询充值详情失败，单号：{}", rechargeNo, e);
            return null;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelRechargeOrder(String rechargeNo, Long buyerUserId) {
        try {
            // 查询充值记录
            Recharge recharge = rechargeDAO.selectByRechargeNo(rechargeNo);
            if (recharge == null) {
                log.warn("充值记录不存在，单号：{}", rechargeNo);
                return false;
            }
            
            // 验证用户权限
            if (!buyerUserId.equals(recharge.getBuyerUserId())) {
                log.warn("用户{}无权取消充值订单{}", buyerUserId, rechargeNo);
                return false;
            }
            
            // 检查充值状态
            if (!WalletConstant.PaymentStatus.PENDING.equals(recharge.getPaymentStatus())) {
                log.warn("充值订单状态不正确，无法取消，单号：{}，状态：{}", rechargeNo, recharge.getPaymentStatus());
                return false;
            }
            
            // 更新充值状态
            String updateTime = TimeUtils.yyMMddHHmmss();
            int result = rechargeDAO.updatePaymentStatus(rechargeNo, 
                                                        WalletConstant.PaymentStatus.CANCELLED,
                                                        null,
                                                        null,
                                                        updateTime);
            
            if (result > 0) {
                log.info("取消充值订单成功，单号：{}，用户：{}", rechargeNo, buyerUserId);
                return true;
            }
            
            return false;
        } catch (Exception e) {
            log.error("取消充值订单失败，单号：{}", rechargeNo, e);
            return false;
        }
    }

    /**
     * 生成充值单号
     * @return 充值单号
     */
    private String generateRechargeNo() {
        return "RC" + TimeUtils.todayTime() + UUID.randomUUID().toString().replace("-", "").substring(0, 8);
    }
}
